#pragma once

#include <iostream>
#include <fstream>
#include <string>
#include <cstdio>
#include <ctime>
#include <cstdarg>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include "LockGuard.hpp"


//存放日志文件
const std::string logname="./log.txt";
//默认输出在屏幕
bool gIsSaveLog=false;

// 日志等级
enum LogLevel
{
    DEBUG = 0,
    INFO,
    WARN,
    ERROR,
    FATAL
};


std::string LogLevel(int level)
{
    switch (level)
    {
    case DEBUG:
        return "DEBUG";
    case INFO:
        return "INFO";
    case WARN:
        return "WARN";
    case ERROR:
        return "ERROR";
    case FATAL:
        return "FATAL";
    default:
        return "UNKNOWN";
    }

    
}

// 将日志信息保存到文件中
void SaveFile(const std::string& log_message,const std::string& filename)
{
    std::ofstream out(logname, std::ios::app);
   
      if(!out.is_open())
      {
        return;
      }

      out<<log_message;
      out.close();
}




/// 获取当前时间
/// 
/// 本函数旨在获取当前系统时间，并以字符串形式返回
/// 时间格式为：YYYY-MM-DD HH:MM:SS
/// 
/// @return 当前时间的字符串表示，如果获取时间失败则返回"None"
std::string GetCurrentTime()
{
   // 获取当前时间的time_t表示
   time_t now=time(nullptr);

   // 将当前时间转换为本地时间的结构体表示
   struct tm *fmt_time=localtime(&now);
   // 如果转换失败，返回错误信息
   if (fmt_time==nullptr)
   {
        return "None";
   }

   // 定义一个字符数组，用于存储格式化后的时间字符串
   char buf_time[1024];
   // 将时间格式化为YYYY-MM-DD HH:MM:SS格式并存储到buf_time中
   snprintf(buf_time, sizeof(buf_time),"%d-%d-%d %d:%d:%d",
   fmt_time->tm_year+1900,
   fmt_time->tm_mon+1,
   fmt_time->tm_mday,
   fmt_time->tm_hour,
   fmt_time->tm_min,
   fmt_time->tm_sec
   );
   
   // 返回格式化后的时间字符串
   return buf_time;
}

//初始化全局或者静态的pthread_mutex_t变量
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;

//日志格式
//日志等级 时间 代码所在文件名/代码所在行数 日志内容
void LogMessage(std::string filename, int line,bool issave, int level, const char *fmt, ...)
{
    //等级数字转换为字符串
   std::string levelStr=LogLevel(level);
   std::string timestr=GetCurrentTime();
   pid_t selfid=getpid();

   char buffer[1024];
   //处理可变参数
   va_list args;
    va_start(args, fmt);
     vsnprintf(buffer, sizeof(buffer), fmt, args);
   va_end(args);

    std::string log_message="["+timestr+"]"+"["+levelStr+"]"+
    "["+filename+":"+std::to_string(line)+"]"+buffer+"\n";

     
    LockGuard lockGuard(&lock);
      if (!issave)
       {
        //设置文本颜色
        //1 加粗 31 红色
            std::string redColor = "\033[1;31m";
           
           std::cout<<redColor<<log_message;
       }
       else
       {
           SaveFile(log_message,logname);
       }

}


//__FILE__ 和 __LINE__ 分别表示当前文件名和行号
//只要穿问题等级和其他要输出的消息
#define LOG(level, format, ...)                                                \
    do                                                                         \
    {                                                                          \
        LogMessage(__FILE__, __LINE__, gIsSaveLog, level, format, ##__VA_ARGS__); \
    } while (0)
//保存至文件
#define EnableFile()    \
    do                  \
    {                   \
        gIsSaveLog = true; \
    } while (0)
    //屏幕输出
#define EnableScreen()   \
    do                   \
    {                    \
        gIsSaveLog = false; \
    } while (0)

